﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ConfigurationForm.cs" company="ScRePt">
//   Copyright © ScRePt 2010 - 2011
// </copyright>
// <summary>
//   The config.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace MP3D.Configuration
{
    #region Using Directives

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.IO;
    using System.Windows.Forms;
    using System.Xml;
    using System.Xml.Serialization;

    using DirectShowLib;
    using Helper;
    using MediaPortal.Configuration;
    using Microsoft.Win32;
    using Stereoscopic;

    #endregion

    /// <summary>
    /// The config.
    /// </summary>
    public partial class ConfigurationForm : Form
    {
        #region Constants and Fields

        /// <summary>
        /// The mode 3 d commands.
        /// </summary>
        private readonly Collection<MenuCommand> mode3DCommands = new Collection<MenuCommand>();

        /// <summary>
        /// The next quick menu commands.
        /// </summary>
        private readonly Collection<MenuCommand> nextQuickMenuCommands = new Collection<MenuCommand>();

        /// <summary>
        /// The ignore events.
        /// </summary>
        private bool ignoreEvents;

        /// <summary>
        /// The initializing.
        /// </summary>
        private bool initializing;

        /// <summary>
        /// The settings.
        /// </summary>
        private Configuration settings;

        /// <summary>
        /// The translation changed.
        /// </summary>
        private bool translationChanged;

        /// <summary>
        /// The translation edit combo box selected index.
        /// </summary>
        private int translationEditComboBoxSelectedIndex;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ConfigurationForm"/> class.
        /// </summary>
        public ConfigurationForm()
        {
            this.InitializeComponent();
            this.Initialize();
        }

        #endregion

        #region Methods

        /// <summary>
        /// The get stereo filter.
        /// </summary>
        /// <returns>
        /// </returns>
        private static DsDevice GetStereoFilter()
        {
            foreach (DsDevice device in DsDevice.GetDevicesOfCat(FilterCategory.LegacyAmFilterCategory))
            {
                try
                {
                    if (device.Name == "3dtv.at Stereo Transformation")
                    {
                        return device;
                    }
                }
                catch
                {
                }
            }

            return null;
        }

        /// <summary>
        /// The set hot key modifier to check box.
        /// </summary>
        /// <param name="hotkeyCheckBox">
        /// The hotkey check box.
        /// </param>
        /// <param name="command">
        /// The command.
        /// </param>
        /// <param name="checkboxModifier">
        /// The checkbox modifier.
        /// </param>
        private static void SetHotKeyModifierToCheckBox(CheckBox hotkeyCheckBox, MenuCommand command, Keys checkboxModifier)
        {
            if (command.HotKeyModifier1 == checkboxModifier || command.HotKeyModifier2 == checkboxModifier || command.HotKeyModifier3 == checkboxModifier)
            {
                hotkeyCheckBox.Checked = true;
            }
        }

        /// <summary>
        /// The cancel button click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void CancelButtonClick(object sender, EventArgs e)
        {
            if (MessageBox.Show("Any unsaved changes will be lost. Are you sure?", "Are you sure?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
            {
                return;
            }

            this.Close();
        }

        /// <summary>
        /// The detect letter box check box validated.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void DetectLetterBoxCheckBoxValidated(object sender, EventArgs e)
        {
            this.settings.DetectLetterbox = this.detectLetterBoxCheckBox.Checked;
        }

        /// <summary>
        /// The initialize.
        /// </summary>
        private void Initialize()
        {
            this.InitializeVersions();
            this.InitializeSettings();
        }

        /// <summary>
        /// The initialize general settings.
        /// </summary>
        private void InitializeGeneralSettings()
        {
            this.loadAutomaticallyCheckBox.Checked = this.settings.LoadAutomatically;
            this.updateProfileCheckBox.Checked = this.settings.UpdateProfile;
            this.parallaxStepNumericUpDown.Value = this.settings.ParallaxStep;
            this.longPressNumericUpDown.Value = this.settings.LongPressMilliseconds;
            this.updateSubtitlesCheckBox.Checked = this.settings.UpdateSubtitles;
            this.detectLetterBoxCheckBox.Checked = this.settings.DetectLetterbox;
            this.stereoscopicMenuCheckBox.Checked = this.settings.StereoscopicMenu;

            foreach (int cmd in this.settings.GlobalCommands)
            {
                if (!this.settings.MenuCommands.ContainsKey(cmd))
                {
                    continue;
                }

                MenuCommand command = this.settings.MenuCommands[cmd];
                if (command.CommandType != MenuCommand.MenuCommandType.SetMode3D)
                {
                    continue;
                }

                this.mode3DCommands.Add(command);
            }

            foreach (KeyValuePair<int, MenuCommand> pair in this.settings.MenuCommands)
            {
                MenuCommand command = pair.Value;

                if (command.Name == "NextQuickMenu")
                {
                    this.nextQuickMenuCommands.Add(command);
                }
            }

            if (this.mode3DCommands.Count > 0)
            {
                this.mode3dHotkey1ComboBox.SelectedIndex = this.mode3dHotkey1ComboBox.Items.IndexOf(this.mode3DCommands[0].HotKey.ToString());
                SetHotKeyModifierToCheckBox(this.mode3dHotkey1ControlModifierCheckBox, this.mode3DCommands[0], Keys.Control);
                SetHotKeyModifierToCheckBox(this.mode3dHotkey1AltModifierCheckBox, this.mode3DCommands[0], Keys.Alt);
                SetHotKeyModifierToCheckBox(this.mode3dHotkey1ShiftModifierCheckBox, this.mode3DCommands[0], Keys.Shift);
            }

            if (this.mode3DCommands.Count > 1)
            {
                this.mode3dHotkey2ComboBox.SelectedIndex = this.mode3dHotkey2ComboBox.Items.IndexOf(this.mode3DCommands[1].HotKey.ToString());
                SetHotKeyModifierToCheckBox(this.mode3dHotkey2ControlModifierCheckBox, this.mode3DCommands[1], Keys.Control);
                SetHotKeyModifierToCheckBox(this.mode3dHotkey2AltModifierCheckBox, this.mode3DCommands[1], Keys.Alt);
                SetHotKeyModifierToCheckBox(this.mode3dHotkey2ShiftModifierCheckBox, this.mode3DCommands[1], Keys.Shift);
            }

            if (this.mode3DCommands.Count > 2)
            {
                this.mode3dHotkey3ComboBox.SelectedIndex = this.mode3dHotkey3ComboBox.Items.IndexOf(this.mode3DCommands[2].HotKey.ToString());
                SetHotKeyModifierToCheckBox(this.mode3dHotkey3ControlModifierCheckBox, this.mode3DCommands[2], Keys.Control);
                SetHotKeyModifierToCheckBox(this.mode3dHotkey3AltModifierCheckBox, this.mode3DCommands[2], Keys.Alt);
                SetHotKeyModifierToCheckBox(this.mode3dHotkey3ShiftModifierCheckBox, this.mode3DCommands[2], Keys.Shift);
            }

            if (this.nextQuickMenuCommands.Count > 0)
            {
                this.nextQuickMenuHotkey1ComboBox.SelectedIndex = this.nextQuickMenuHotkey1ComboBox.Items.IndexOf(this.nextQuickMenuCommands[0].HotKey.ToString());
                SetHotKeyModifierToCheckBox(this.nextQuickMenuHotkey1ControlModifierCheckBox, this.nextQuickMenuCommands[0], Keys.Control);
                SetHotKeyModifierToCheckBox(this.nextQuickMenuHotkey1AltModifierCheckBox, this.nextQuickMenuCommands[0], Keys.Alt);
                SetHotKeyModifierToCheckBox(this.nextQuickMenuHotkey1ShiftModifierCheckBox, this.nextQuickMenuCommands[0], Keys.Shift);
            }

            if (this.nextQuickMenuCommands.Count > 1)
            {
                this.nextQuickMenuHotkey2ComboBox.SelectedIndex = this.nextQuickMenuHotkey2ComboBox.Items.IndexOf(this.nextQuickMenuCommands[1].HotKey.ToString());
                SetHotKeyModifierToCheckBox(this.nextQuickMenuHotkey2ControlModifierCheckBox, this.nextQuickMenuCommands[1], Keys.Control);
                SetHotKeyModifierToCheckBox(this.nextQuickMenuHotkey2AltModifierCheckBox, this.nextQuickMenuCommands[1], Keys.Alt);
                SetHotKeyModifierToCheckBox(this.nextQuickMenuHotkey2ShiftModifierCheckBox, this.nextQuickMenuCommands[1], Keys.Shift);
            }

            if (this.nextQuickMenuCommands.Count > 2)
            {
                this.nextQuickMenuHotkey3ComboBox.SelectedIndex = this.nextQuickMenuHotkey3ComboBox.Items.IndexOf(this.nextQuickMenuCommands[2].HotKey.ToString());
                SetHotKeyModifierToCheckBox(this.nextQuickMenuHotkey3ControlModifierCheckBox, this.nextQuickMenuCommands[2], Keys.Control);
                SetHotKeyModifierToCheckBox(this.nextQuickMenuHotkey3AltModifierCheckBox, this.nextQuickMenuCommands[2], Keys.Alt);
                SetHotKeyModifierToCheckBox(this.nextQuickMenuHotkey3ShiftModifierCheckBox, this.nextQuickMenuCommands[2], Keys.Shift);
            }
        }

        /// <summary>
        /// The initialize gui.
        /// </summary>
        private void InitializeGui()
        {
            string[] keysEnumeration = Enum.GetNames(typeof(Keys));
            this.mode3dHotkey1ComboBox.Items.AddRange(keysEnumeration);
            this.mode3dHotkey2ComboBox.Items.AddRange(keysEnumeration);
            this.mode3dHotkey3ComboBox.Items.AddRange(keysEnumeration);
            this.nextQuickMenuHotkey1ComboBox.Items.AddRange(keysEnumeration);
            this.nextQuickMenuHotkey2ComboBox.Items.AddRange(keysEnumeration);
            this.nextQuickMenuHotkey3ComboBox.Items.AddRange(keysEnumeration);
            this.mode3dHotkey1ComboBox.SelectedIndex = this.mode3dHotkey1ComboBox.Items.IndexOf("None");
            this.mode3dHotkey1ComboBox.SelectedIndex = this.mode3dHotkey1ComboBox.Items.IndexOf("None");
            this.mode3dHotkey1ComboBox.SelectedIndex = this.mode3dHotkey1ComboBox.Items.IndexOf("None");
            this.nextQuickMenuHotkey1ComboBox.SelectedIndex = this.mode3dHotkey1ComboBox.Items.IndexOf("None");
            this.nextQuickMenuHotkey2ComboBox.SelectedIndex = this.mode3dHotkey1ComboBox.Items.IndexOf("None");
            this.nextQuickMenuHotkey3ComboBox.SelectedIndex = this.mode3dHotkey1ComboBox.Items.IndexOf("None");
            this.mode3dHotkey1ControlModifierCheckBox.Checked = false;
            this.mode3dHotkey1AltModifierCheckBox.Checked = false;
            this.mode3dHotkey1ShiftModifierCheckBox.Checked = false;
            this.mode3dHotkey2ControlModifierCheckBox.Checked = false;
            this.mode3dHotkey2AltModifierCheckBox.Checked = false;
            this.mode3dHotkey2ShiftModifierCheckBox.Checked = false;
            this.mode3dHotkey3ControlModifierCheckBox.Checked = false;
            this.mode3dHotkey3AltModifierCheckBox.Checked = false;
            this.mode3dHotkey3ShiftModifierCheckBox.Checked = false;
            this.nextQuickMenuHotkey1ControlModifierCheckBox.Checked = false;
            this.nextQuickMenuHotkey1AltModifierCheckBox.Checked = false;
            this.nextQuickMenuHotkey1ShiftModifierCheckBox.Checked = false;
            this.nextQuickMenuHotkey2ControlModifierCheckBox.Checked = false;
            this.nextQuickMenuHotkey2AltModifierCheckBox.Checked = false;
            this.nextQuickMenuHotkey2ShiftModifierCheckBox.Checked = false;
            this.nextQuickMenuHotkey3ControlModifierCheckBox.Checked = false;
            this.nextQuickMenuHotkey3AltModifierCheckBox.Checked = false;
            this.nextQuickMenuHotkey3ShiftModifierCheckBox.Checked = false;

            this.profilesComboBox.Items.Clear();
            this.profilePropertiesListBox.Items.Clear();
        }

        /// <summary>
        /// The initialize profile settings.
        /// </summary>
        private void InitializeProfileSettings()
        {
            Profile[] profiles = new Profile[this.settings.Profiles.Values.Count];
            this.settings.Profiles.Values.CopyTo(profiles, 0);
            this.profilesComboBox.Items.AddRange(profiles);

            FilterProperty[] properties = new FilterProperty[this.settings.FilterProperties.Values.Count];
            this.settings.FilterProperties.Values.CopyTo(properties, 0);
            this.profilePropertiesListBox.Items.AddRange(properties);

            this.profilesComboBox.SelectedIndex = 0;
        }

        /// <summary>
        /// The initialize quick menu settings.
        /// </summary>
        private void InitializeQuickMenuSettings()
        {
            this.quickMenuSourceFormatCheckedListBox.Items.Clear();
            this.quickMenuOutputFormatCheckedListBox.Items.Clear();

            foreach (KeyValuePair<int, FilterPropertyValue> pair in this.settings.FilterPropertyValues)
            {
                FilterPropertyValue property = pair.Value;

                if (!property.Supported)
                {
                    continue;
                }

                if (((FilterPropertyEnum)this.settings.FilterProperties[1]).FilterPropertyValueIds.Contains(property.Id))
                {
                    this.quickMenuSourceFormatCheckedListBox.Items.Add(property, property.Enabled);
                    continue;
                }

                if (((FilterPropertyEnum)this.settings.FilterProperties[2]).FilterPropertyValueIds.Contains(property.Id))
                {
                    this.quickMenuOutputFormatCheckedListBox.Items.Add(property, property.Enabled);
                }
            }
        }

        /// <summary>
        /// The initialize settings.
        /// </summary>
        private void InitializeSettings()
        {
            this.initializing = true;
            this.translationChanged = false;

            if (!this.LoadSettings())
            {
                this.settings = new Configuration();
                this.settings.Initialize();
            }

            this.InitializeGui();
            this.InitializeGeneralSettings();
            this.InitializeProfileSettings();
            this.InitializeQuickMenuSettings();
            this.InitializeTranslationSettings();

            this.initializing = false;
        }

        /// <summary>
        /// The initialize translation settings.
        /// </summary>
        private void InitializeTranslationSettings()
        {
            this.translationEditComboBox.Items.Clear();
            this.translationReferenceComboBox.Items.Clear();
            this.translationDataGridView.Rows.Clear();
            this.translationReferenceComboBox.Items.Add("en");
            this.translationReferenceComboBox.SelectedIndex = 0;

            if (Directory.Exists(Translations.GetPluginLanguagesPath()))
            {
                foreach (FileInfo file in new DirectoryInfo(Translations.GetPluginLanguagesPath()).GetFiles())
                {
                    if (!file.Name.EndsWith(".xml"))
                    {
                        continue;
                    }

                    string language = file.Name.Substring(0, file.Name.Length - ".xml".Length);

                    if (language == "en")
                    {
                        continue;
                    }

                    this.translationReferenceComboBox.Items.Add(language);
                }
            }

            foreach (FileInfo file in Config.GetDirectoryInfo(Config.Dir.Language).GetFiles())
            {
                if (!file.Name.StartsWith("strings_") || !file.Name.EndsWith(".xml"))
                {
                    continue;
                }

                string language = file.Name.Substring("strings_".Length, file.Name.Length - "strings_".Length - ".xml".Length);

                int i = this.translationEditComboBox.Items.Add(language);

                if (language == "en")
                {
                    this.translationEditComboBox.SelectedIndex = i;
                }
            }

            if (this.translationEditComboBox.SelectedIndex == -1)
            {
                this.translationEditComboBox.SelectedIndex = 0;
            }
        }

        /// <summary>
        /// The initialize versions.
        /// </summary>
        private void InitializeVersions()
        {
            this.pluginVersionLabel.Text = Helper.PluginVersion;
            this.filterVersionLabel.Text = "Filter not found!";

            DsDevice stereoFilter = GetStereoFilter();

            if (stereoFilter == null)
            {
                return;
            }

            int clsidIndex = stereoFilter.DevicePath.LastIndexOf("{");
            string clsid = string.Empty;

            if (clsidIndex > 0)
            {
                clsid = stereoFilter.DevicePath.Substring(clsidIndex);
            }

            RegistryKey r = Registry.ClassesRoot.OpenSubKey(@"CLSID\" + clsid + @"\InprocServer32");

            if (r != null)
            {
                this.filterVersionLabel.Text = r.GetValue(string.Empty, this.filterVersionLabel.Text).ToString();

                if (File.Exists(this.filterVersionLabel.Text))
                {
                    this.filterVersionLabel.Text = FileVersionInfo.GetVersionInfo(this.filterVersionLabel.Text).FileVersion;
                }
            }
        }

        /// <summary>
        /// The load automatically check box validated.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void LoadAutomaticallyCheckBoxValidated(object sender, EventArgs e)
        {
            this.settings.LoadAutomatically = this.loadAutomaticallyCheckBox.Checked;
        }

        /// <summary>
        /// The load settings.
        /// </summary>
        /// <returns>
        /// The load settings.
        /// </returns>
        private bool LoadSettings()
        {
            try
            {
                XmlSerializer ser = new XmlSerializer(typeof(Configuration));
                FileStream stream = new FileStream(Helper.ConfigFile, FileMode.Open, FileAccess.Read);
                object o = ser.Deserialize(stream);
                this.settings = (Configuration)o;
                stream.Close();

                if (!this.settings.VerifyConfiguration())
                {
                    MainWindow.LogWarn("LoadSettings", "Settings could not be verified");
                    return false;
                }

                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// The long press numeric up down value changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void LongPressNumericUpDownValueChanged(object sender, EventArgs e)
        {
            this.settings.LongPressMilliseconds = (int)this.longPressNumericUpDown.Value;
        }

        /// <summary>
        /// The mode 3 d hotkey 1 alt modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey1AltModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 0, 2, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 1 combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey1ComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            this.UpdateHotkey(sender, 0, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 1 control modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey1ControlModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 0, 1, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 1 shift modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey1ShiftModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 0, 3, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 2 alt modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey2AltModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 1, 2, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 2 combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey2ComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            this.UpdateHotkey(sender, 1, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 2 control modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey2ControlModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 1, 1, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 2 shift modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey2ShiftModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 1, 3, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 3 alt modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey3AltModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 2, 2, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 3 combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey3ComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            this.UpdateHotkey(sender, 2, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 3 control modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey3ControlModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 2, 1, this.mode3DCommands);
        }

        /// <summary>
        /// The mode 3 d hotkey 3 shift modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Mode3DHotkey3ShiftModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 2, 3, this.mode3DCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 1 alt modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey1AltModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 0, 2, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 1 combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey1ComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            this.UpdateHotkey(sender, 0, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 1 control modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey1ControlModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 0, 1, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 1 shift modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey1ShiftModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 0, 3, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 2 alt modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey2AltModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 1, 2, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 2 combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey2ComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            this.UpdateHotkey(sender, 1, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 2 control modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey2ControlModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 1, 1, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 2 shift modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey2ShiftModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 1, 3, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 3 alt modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey3AltModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 2, 2, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 3 combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey3ComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            this.UpdateHotkey(sender, 2, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 3 control modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey3ControlModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 2, 1, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The next quick menu hotkey 3 shift modifier check box checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void NextQuickMenuHotkey3ShiftModifierCheckBoxCheckedChanged(object sender, EventArgs e)
        {
            this.UpdateHotkeyModifier(sender, 2, 3, this.nextQuickMenuCommands);
        }

        /// <summary>
        /// The parallax step numeric up down value changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ParallaxStepNumericUpDownValueChanged(object sender, EventArgs e)
        {
            this.settings.ParallaxStep = (int)this.parallaxStepNumericUpDown.Value;
        }

        /// <summary>
        /// The profile add button click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfileAddButtonClick(object sender, EventArgs e)
        {
            Profile profile = new Profile { Name = "New profile", Enabled = true };

            // SourceFormat
            profile.ProfileProperties.Add(1, new ProfileProperty { PropertyId = 1, DefaultValue = TSTFConfig.LAYOUT_MONOSCOPIC, PropertyType = ProfileProperty.ProfilePropertyType.SaveGlobally });

            // OutputFormat
            profile.ProfileProperties.Add(2, new ProfileProperty { PropertyId = 2, DefaultValue = CONSTS.METHOD_SOURCE, PropertyType = ProfileProperty.ProfilePropertyType.SaveGlobally });

            // Horizontal Parallax
            profile.ProfileProperties.Add(3, new ProfileProperty { PropertyId = 3, DefaultValue = 0, PropertyType = ProfileProperty.ProfilePropertyType.SaveGlobally });

            // Vertical Parallax
            profile.ProfileProperties.Add(4, new ProfileProperty { PropertyId = 4, DefaultValue = 0, PropertyType = ProfileProperty.ProfilePropertyType.SaveGlobally });

            this.profilesComboBox.SelectedIndex = this.profilesComboBox.Items.Add(profile);
        }

        /// <summary>
        /// The profile delete button click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfileDeleteButtonClick(object sender, EventArgs e)
        {
            if (this.profilesComboBox.Items.Count <= 1)
            {
                return;
            }

            if (MessageBox.Show("Are you sure?", "Confirm deletion", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
            {
                return;
            }

            this.profilesComboBox.Items.Remove(this.profilesComboBox.SelectedItem);
            this.profilesComboBox.SelectedIndex = 0;
        }

        /// <summary>
        /// The profile enabled check box validated.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfileEnabledCheckBoxValidated(object sender, EventArgs e)
        {
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null)
            {
                return;
            }

            profile.Enabled = this.profileEnabledCheckBox.Checked;
        }

        /// <summary>
        /// The profile name text box validated.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfileNameTextBoxValidated(object sender, EventArgs e)
        {
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null)
            {
                return;
            }

            profile.Name = this.profileNameTextBox.Text;
            this.ignoreEvents = true;
            this.profilesComboBox.Items.Remove(profile);
            this.profilesComboBox.SelectedIndex = this.profilesComboBox.Items.Add(profile);
            this.ignoreEvents = false;
        }

        /// <summary>
        /// The profile name text box validating.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfileNameTextBoxValidating(object sender, CancelEventArgs e)
        {
            this.errorProvider.SetError(this.profileNameTextBox, string.Empty);

            if (this.profileNameTextBox.Text.Length == 0)
            {
                e.Cancel = true;
                this.errorProvider.SetError(this.profileNameTextBox, "Profile name can not be empty");
            }
        }

        /// <summary>
        /// The profile properties list box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertiesListBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            this.UpdateProfileProperties();
        }

        /// <summary>
        /// The profile property default combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyDefaultComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null || property == null)
            {
                return;
            }

            foreach (KeyValuePair<int, ProfileProperty> pair in profile.ProfileProperties)
            {
                ProfileProperty prop = pair.Value;

                if (prop.PropertyId == property.Id)
                {
                    if (this.profilePropertyDefaultComboBox.SelectedItem == null)
                    {
                        prop.DefaultValue = 0;
                        return;
                    }

                    prop.DefaultValue = ((FilterPropertyValue)this.profilePropertyDefaultComboBox.SelectedItem).Value;
                    return;
                }
            }
        }

        /// <summary>
        /// The profile property default numeric up down value changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyDefaultNumericUpDownValueChanged(object sender, EventArgs e)
        {
            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null || property == null)
            {
                return;
            }

            foreach (KeyValuePair<int, ProfileProperty> pair in profile.ProfileProperties)
            {
                ProfileProperty prop = pair.Value;

                if (prop.PropertyId == property.Id)
                {
                    prop.DefaultValue = (int)this.profilePropertyDefaultNumericUpDown.Value;
                    return;
                }
            }
        }

        /// <summary>
        /// The profile property per media tv combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyPerMediaTvComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null || property == null)
            {
                return;
            }

            foreach (KeyValuePair<int, ProfileProperty> pair in profile.ProfileProperties)
            {
                if (!(pair.Value is ProfilePropertyPerMediaType) || pair.Value.PropertyId != property.Id)
                {
                    continue;
                }

                ProfilePropertyPerMediaType prop = (ProfilePropertyPerMediaType)pair.Value;

                if (this.profilePropertyPerMediaTvComboBox.SelectedItem == null)
                {
                    if (prop.Value.ContainsKey(MediaPortal.Player.g_Player.MediaType.TV))
                    {
                        prop.Value.Remove(MediaPortal.Player.g_Player.MediaType.TV);
                    }

                    return;
                }

                int newValue = ((FilterPropertyValue)this.profilePropertyPerMediaTvComboBox.SelectedItem).Value;

                if (prop.Value.ContainsKey(MediaPortal.Player.g_Player.MediaType.TV))
                {
                    prop.Value[MediaPortal.Player.g_Player.MediaType.TV] = newValue;
                }
                else
                {
                    prop.Value.Add(MediaPortal.Player.g_Player.MediaType.TV, newValue);
                }

                return;
            }
        }

        /// <summary>
        /// The profile property per media tv numeric up down value changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyPerMediaTvNumericUpDownValueChanged(object sender, EventArgs e)
        {
            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null || property == null)
            {
                return;
            }

            foreach (KeyValuePair<int, ProfileProperty> pair in profile.ProfileProperties)
            {
                if (!(pair.Value is ProfilePropertyPerMediaType) || pair.Value.PropertyId != property.Id)
                {
                    continue;
                }

                ProfilePropertyPerMediaType prop = (ProfilePropertyPerMediaType)pair.Value;
                int newValue = (int)this.profilePropertyPerMediaTvNumericUpDown.Value;

                if (prop.Value.ContainsKey(MediaPortal.Player.g_Player.MediaType.TV))
                {
                    prop.Value[MediaPortal.Player.g_Player.MediaType.TV] = newValue;
                }
                else
                {
                    prop.Value.Add(MediaPortal.Player.g_Player.MediaType.TV, newValue);
                }

                return;
            }
        }

        /// <summary>
        /// The profile property per media video combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyPerMediaVideoComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null || property == null)
            {
                return;
            }

            foreach (KeyValuePair<int, ProfileProperty> pair in profile.ProfileProperties)
            {
                if (!(pair.Value is ProfilePropertyPerMediaType) || pair.Value.PropertyId != property.Id)
                {
                    continue;
                }

                ProfilePropertyPerMediaType prop = (ProfilePropertyPerMediaType)pair.Value;

                if (this.profilePropertyPerMediaVideoComboBox.SelectedItem == null)
                {
                    if (prop.Value.ContainsKey(MediaPortal.Player.g_Player.MediaType.Video))
                    {
                        prop.Value.Remove(MediaPortal.Player.g_Player.MediaType.Video);
                    }

                    return;
                }

                int newValue = ((FilterPropertyValue)this.profilePropertyPerMediaVideoComboBox.SelectedItem).Value;

                if (prop.Value.ContainsKey(MediaPortal.Player.g_Player.MediaType.Video))
                {
                    prop.Value[MediaPortal.Player.g_Player.MediaType.Video] = newValue;
                }
                else
                {
                    prop.Value.Add(MediaPortal.Player.g_Player.MediaType.Video, newValue);
                }

                return;
            }
        }

        /// <summary>
        /// The profile property per media video numeric up down value changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyPerMediaVideoNumericUpDownValueChanged(object sender, EventArgs e)
        {
            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null || property == null)
            {
                return;
            }

            foreach (KeyValuePair<int, ProfileProperty> pair in profile.ProfileProperties)
            {
                if (!(pair.Value is ProfilePropertyPerMediaType) || pair.Value.PropertyId != property.Id)
                {
                    continue;
                }

                ProfilePropertyPerMediaType prop = (ProfilePropertyPerMediaType)pair.Value;
                int newValue = (int)this.profilePropertyPerMediaVideoNumericUpDown.Value;

                if (prop.Value.ContainsKey(MediaPortal.Player.g_Player.MediaType.Video))
                {
                    prop.Value[MediaPortal.Player.g_Player.MediaType.Video] = newValue;
                }
                else
                {
                    prop.Value.Add(MediaPortal.Player.g_Player.MediaType.Video, newValue);
                }

                return;
            }
        }

        /// <summary>
        /// The profile property per source data grid view cell validating.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyPerSourceDataGridViewCellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            if (e.RowIndex == this.profilePropertyPerSourceDataGridView.Rows.Count - 1)
            {
                return;
            }

            this.profilePropertyPerSourceDataGridView.Rows[e.RowIndex].ErrorText = string.Empty;

            if (e.ColumnIndex == this.hashColumn.Index)
            {
                if (e.FormattedValue == null || e.FormattedValue.ToString().Length == 0)
                {
                    e.Cancel = true;
                    this.profilePropertyPerSourceDataGridView.Rows[e.RowIndex].ErrorText = "Filename or channel can not be empty";
                }

                return;
            }

            if (e.ColumnIndex == this.valueColumn.Index)
            {
                if (e.FormattedValue == null)
                {
                    e.Cancel = true;
                    this.profilePropertyPerSourceDataGridView.Rows[e.RowIndex].ErrorText = "Integer expected";
                    return;
                }

                int result;

                if (!int.TryParse(e.FormattedValue.ToString(), out result))
                {
                    e.Cancel = true;
                    this.profilePropertyPerSourceDataGridView.Rows[e.RowIndex].ErrorText = "Integer expected";
                    return;
                }
            }

            if (e.ColumnIndex == this.valueEnumColumn.Index)
            {
                if (e.FormattedValue == null)
                {
                    e.Cancel = true;
                    this.profilePropertyPerSourceDataGridView.Rows[e.RowIndex].ErrorText = "Please select a value from the drop down list";
                    return;
                }
            }
        }

        /// <summary>
        /// The profile property per source data grid view cell value changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyPerSourceDataGridViewCellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null || property == null)
            {
                return;
            }

            foreach (KeyValuePair<int, ProfileProperty> pair in profile.ProfileProperties)
            {
                if (!(pair.Value is ProfilePropertyPerSource) || pair.Value.PropertyId != property.Id)
                {
                    continue;
                }

                ProfilePropertyPerSource prop = (ProfilePropertyPerSource)pair.Value;

                string hash = this.profilePropertyPerSourceDataGridView.Rows[e.RowIndex].Cells[this.hashColumn.Index].Value.ToString();

                if (hash == string.Empty)
                {
                    return;
                }

                int newValue;

                if (property is FilterPropertyEnum)
                {
                    DataGridViewComboBoxCell cell = (DataGridViewComboBoxCell)this.profilePropertyPerSourceDataGridView.Rows[e.RowIndex].Cells[this.valueEnumColumn.Index];

                    if (cell == null || cell.Value == null)
                    {
                        return;
                    }

                    newValue = ((FilterPropertyValue)cell.Value).Value;
                }
                else
                {
                    if (this.profilePropertyPerSourceDataGridView.Rows[e.RowIndex].Cells[this.valueColumn.Index].Value == null)
                    {
                        return;
                    }

                    newValue = int.Parse(this.profilePropertyPerSourceDataGridView.Rows[e.RowIndex].Cells[this.valueColumn.Index].Value.ToString());
                }

                if (prop.Value.ContainsKey(hash))
                {
                    prop.Value[hash] = newValue;
                }
                else
                {
                    prop.Value.Add(hash, newValue);
                }

                Collection<string> removeHash = new Collection<string>();

                foreach (KeyValuePair<string, int> pair2 in prop.Value)
                {
                    bool found = false;

                    foreach (DataGridViewRow row in this.profilePropertyPerSourceDataGridView.Rows)
                    {
                        if (row.Cells[this.hashColumn.Index].Value != null && row.Cells[this.hashColumn.Index].Value.ToString() == pair2.Key)
                        {
                            found = true;
                        }
                    }

                    if (!found)
                    {
                        removeHash.Add(pair2.Key);
                    }
                }

                foreach (string h in removeHash)
                {
                    prop.Value.Remove(h);
                }

                return;
            }
        }

        /// <summary>
        /// The profile property per source data grid view data error.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyPerSourceDataGridViewDataError(object sender, DataGridViewDataErrorEventArgs e)
        {
        }

        /// <summary>
        /// The profile property per source data grid view rows removed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyPerSourceDataGridViewRowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
        {
            if (this.ignoreEvents)
            {
                return;
            }

            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null || property == null)
            {
                return;
            }

            foreach (KeyValuePair<int, ProfileProperty> pair in profile.ProfileProperties)
            {
                if (!(pair.Value is ProfilePropertyPerSource) || pair.Value.PropertyId != property.Id)
                {
                    continue;
                }

                ProfilePropertyPerSource prop = (ProfilePropertyPerSource)pair.Value;

                Collection<string> removeHash = new Collection<string>();

                foreach (KeyValuePair<string, int> pair2 in prop.Value)
                {
                    bool found = false;

                    foreach (DataGridViewRow row in this.profilePropertyPerSourceDataGridView.Rows)
                    {
                        if (row.Cells[this.hashColumn.Index].Value != null && row.Cells[this.hashColumn.Index].Value.ToString() == pair2.Key)
                        {
                            found = true;
                        }
                    }

                    if (!found)
                    {
                        removeHash.Add(pair2.Key);
                    }
                }

                foreach (string h in removeHash)
                {
                    prop.Value.Remove(h);
                }

                return;
            }
        }

        /// <summary>
        /// The profile property type global radio button checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyTypeGlobalRadioButtonCheckedChanged(object sender, EventArgs e)
        {
            if (this.ignoreEvents)
            {
                return;
            }

            if (!this.profilePropertyTypeGlobalRadioButton.Checked)
            {
                return;
            }

            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (property == null || profile == null)
            {
                return;
            }

            ProfileProperty prop = profile.ProfileProperties[property.Id];

            if (prop is ProfilePropertyPerMediaType || prop is ProfilePropertyPerSource)
            {
                if (MessageBox.Show("Any media type or source specific information currently stored will be lost. Are you sure?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
                {
                    return;
                }
            }

            ProfileProperty clone = new ProfileProperty();
            prop.CloneTo(clone);
            profile.ProfileProperties[property.Id] = clone;
            this.UpdateProfileProperties();
        }

        /// <summary>
        /// The profile property type per media type radio button checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyTypePerMediaTypeRadioButtonCheckedChanged(object sender, EventArgs e)
        {
            if (this.ignoreEvents)
            {
                return;
            }

            if (!this.profilePropertyTypePerMediaTypeRadioButton.Checked)
            {
                return;
            }

            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (property == null || profile == null)
            {
                return;
            }

            ProfileProperty prop = profile.ProfileProperties[property.Id];

            if (prop is ProfilePropertyPerSource)
            {
                if (MessageBox.Show("Any source specific information currently stored will be lost. Are you sure?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
                {
                    return;
                }
            }

            ProfilePropertyPerMediaType clone = new ProfilePropertyPerMediaType();
            prop.CloneTo(clone);
            profile.ProfileProperties[property.Id] = clone;
            this.UpdateProfileProperties();
        }

        /// <summary>
        /// The profile property type per source radio button checked changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilePropertyTypePerSourceRadioButtonCheckedChanged(object sender, EventArgs e)
        {
            if (this.ignoreEvents)
            {
                return;
            }

            if (!this.profilePropertyTypePerSourceRadioButton.Checked)
            {
                return;
            }

            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (property == null || profile == null)
            {
                return;
            }

            ProfileProperty prop = profile.ProfileProperties[property.Id];

            if (prop is ProfilePropertyPerMediaType)
            {
                if (MessageBox.Show("Any media type specific information currently stored will be lost. Are you sure?", "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
                {
                    return;
                }
            }

            ProfilePropertyPerSource clone = new ProfilePropertyPerSource();
            prop.CloneTo(clone);
            profile.ProfileProperties[property.Id] = clone;
            this.UpdateProfileProperties();
        }

        /// <summary>
        /// The profiles combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ProfilesComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            Profile profile = this.profilesComboBox.SelectedItem as Profile;

            if (profile == null)
            {
                this.profileDeleteButton.Enabled = false;
                this.profileNameTextBox.Text = string.Empty;
                this.profileEnabledCheckBox.Checked = false;
            }
            else
            {
                this.profileDeleteButton.Enabled = this.profilesComboBox.Items.Count > 1;
                this.profileNameTextBox.Text = profile.Name;
                this.profileEnabledCheckBox.Checked = profile.Enabled;
            }

            this.profilePropertiesListBox.SelectedIndex = 0;
            this.UpdateProfileProperties();
        }

        /// <summary>
        /// The quick menu output format checked list box item check.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void QuickMenuOutputFormatCheckedListBoxItemCheck(object sender, ItemCheckEventArgs e)
        {
            FilterPropertyValue property = (FilterPropertyValue)this.quickMenuOutputFormatCheckedListBox.Items[e.Index];
            property.Enabled = e.NewValue == CheckState.Checked;
        }

        /// <summary>
        /// The quick menu source format checked list box item check.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void QuickMenuSourceFormatCheckedListBoxItemCheck(object sender, ItemCheckEventArgs e)
        {
            FilterPropertyValue property = (FilterPropertyValue)this.quickMenuSourceFormatCheckedListBox.Items[e.Index];
            property.Enabled = e.NewValue == CheckState.Checked;
        }

        /// <summary>
        /// The save button click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void SaveButtonClick(object sender, EventArgs e)
        {
            Profile currentProfile;

            if (this.settings.Profiles.ContainsKey(this.settings.CurrentProfile))
            {
                currentProfile = this.settings.Profiles[this.settings.CurrentProfile];
            }
            else
            {
                currentProfile = this.settings.Profiles[0];
            }

            SerializableDictionary<int, Profile> profiles = new SerializableDictionary<int, Profile>();
            int i = 0;

            foreach (Profile profile in this.profilesComboBox.Items)
            {
                i++;

                profiles.Add(i, profile);
                profile.Id = i;
            }

            this.settings.Profiles = profiles;
            this.settings.CurrentProfile = currentProfile.Id;

            this.SaveSettings();
            this.Close();
        }

        /// <summary>
        /// The save settings.
        /// </summary>
        private void SaveSettings()
        {
            if (this.settings == null)
            {
                return;
            }

            XmlSerializer ser = new XmlSerializer(typeof(Configuration));
            FileStream stream = new FileStream(Helper.ConfigFile, FileMode.Create, FileAccess.Write);
            ser.Serialize(stream, this.settings);
            stream.Close();

            if (this.translationChanged)
            {
                this.SaveTranslation();
            }
        }

        /// <summary>
        /// The save translation.
        /// </summary>
        private void SaveTranslation()
        {
            if (this.translationEditComboBox.SelectedItem == null)
            {
                return;
            }

            string language = (string)this.translationEditComboBox.SelectedItem;
            string languageFilePath = Path.Combine(Translations.GetPluginLanguagesPath(), language + ".xml");
            using (XmlTextWriter writer = new XmlTextWriter(languageFilePath, System.Text.Encoding.UTF8))
            {
                writer.Formatting = Formatting.Indented;
                writer.WriteStartDocument();
                writer.WriteComment("MP3D translation file");
                writer.WriteComment("Language: " + language);
                writer.WriteComment("Note: English is the fallback for any strings not found in other languages");
                writer.WriteComment("Contributed by [Your Name]");
                writer.WriteComment("=========================================================================");
                writer.WriteStartElement("strings"); // <-- Important root element 
                foreach (DataGridViewRow row in this.translationDataGridView.Rows)
                {
                    writer.WriteStartElement("string");
                    writer.WriteAttributeString("Field", row.Cells[this.keyColumn.Index].Value.ToString());
                    writer.WriteValue(row.Cells[this.valueColumn.Index].Value.ToString());
                    writer.WriteEndElement();
                }

                writer.WriteEndElement(); // <-- Closes it 
                writer.WriteEndDocument();
                writer.Flush();
                writer.Close();
            }
        }

        /// <summary>
        /// The translation data grid view cell value changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void TranslationDataGridViewCellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (this.ignoreEvents)
            {
                return;
            }

            this.translationChanged = true;
        }

        /// <summary>
        /// The translation edit combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void TranslationEditComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.ignoreEvents)
            {
                return;
            }

            if (this.translationEditComboBox.SelectedItem == null)
            {
                this.translationEditComboBoxSelectedIndex = this.translationEditComboBox.SelectedIndex;
                return;
            }

            if (this.translationChanged && !this.initializing)
            {
                if (MessageBox.Show("Any unsaved translation values will be lost. Are you sure?", "Are you sure?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.No)
                {
                    this.ignoreEvents = true;
                    this.translationEditComboBox.SelectedIndex = this.translationEditComboBoxSelectedIndex;
                    this.ignoreEvents = false;
                    return;
                }
            }

            this.ignoreEvents = true;
            this.translationEditComboBoxSelectedIndex = this.translationEditComboBox.SelectedIndex;
            string lang = (string)this.translationEditComboBox.SelectedItem;
            string finalLang;
            int count = Translations.LoadTranslations(lang, out finalLang);

            if (lang != "en" && (count == 0 || finalLang != lang))
            {
                foreach (DataGridViewRow row in this.translationDataGridView.Rows)
                {
                    row.Cells[this.valueColumn.Index].Value = string.Empty;
                }

                this.ignoreEvents = false;
                return;
            }

            int i = 0;

            foreach (KeyValuePair<string, string> pair in Translations.LocalizedStrings)
            {
                if (this.translationDataGridView.Rows[i].Cells[this.keyColumn.Index].Value != null && this.translationDataGridView.Rows[i].Cells[this.keyColumn.Index].Value.ToString() == pair.Key)
                {
                    this.translationDataGridView.Rows[i].Cells[this.valueColumn.Index].Value = pair.Value;
                }
                else
                {
                    bool found = false;

                    foreach (DataGridViewRow row in this.translationDataGridView.Rows)
                    {
                        if (row.Cells[this.keyColumn.Index].Value.ToString() == pair.Key)
                        {
                            row.Cells[this.valueColumn.Index].Value = pair.Value;
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        this.translationDataGridView.Rows.Add(pair.Key, string.Empty, pair.Value);
                    }
                }

                i++;
            }

            this.ignoreEvents = false;
        }

        /// <summary>
        /// The translation open folder button click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void TranslationOpenFolderButtonClick(object sender, EventArgs e)
        {
            if (!Config.GetDirectoryInfo(Config.Dir.Language).Exists)
            {
                MessageBox.Show("MediaPortal configuration folder was not found!!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            string path = Config.GetDirectoryInfo(Config.Dir.Language).FullName;
            string args = string.Empty;

            if (Directory.Exists(Translations.GetPluginLanguagesPath()))
            {
                path = Translations.GetPluginLanguagesPath();

                if (this.translationEditComboBox.SelectedItem != null && File.Exists(Path.Combine(path, this.translationEditComboBox.SelectedItem + ".xml")))
                {
                    args = "/select, " + Path.Combine(path, this.translationEditComboBox.SelectedItem + ".xml");
                    path = "explorer.exe";
                }
            }

            Process.Start(path, args);
        }

        /// <summary>
        /// The translation reference combo box selected index changed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void TranslationReferenceComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            if (this.translationReferenceComboBox.SelectedItem == null)
            {
                return;
            }

            string lang = (string)this.translationReferenceComboBox.SelectedItem;
            string finalLang;
            Translations.LoadTranslations(lang, out finalLang);

            if (this.translationDataGridView.Rows.Count == 0)
            {
                foreach (KeyValuePair<string, string> pair in Translations.LocalizedStrings)
                {
                    this.translationDataGridView.Rows.Add(pair.Key, pair.Value, string.Empty);
                }
            }
            else
            {
                int i = 0;

                foreach (KeyValuePair<string, string> pair in Translations.LocalizedStrings)
                {
                    if (this.translationDataGridView.Rows[i].Cells[this.keyColumn.Index].Value != null && this.translationDataGridView.Rows[i].Cells[this.keyColumn.Index].Value.ToString() == pair.Key)
                    {
                        this.translationDataGridView.Rows[i].Cells[this.referenceValueColumn.Index].Value = pair.Value;
                    }
                    else
                    {
                        bool found = false;

                        foreach (DataGridViewRow row in this.translationDataGridView.Rows)
                        {
                            if (row.Cells[this.keyColumn.Index].Value.ToString() == pair.Key)
                            {
                                row.Cells[this.referenceValueColumn.Index].Value = pair.Value;
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            this.translationDataGridView.Rows.Add(pair.Key, pair.Value, string.Empty);
                        }
                    }

                    i++;
                }
            }
        }

        /// <summary>
        /// The update hotkey.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="commandIndex">
        /// The command index.
        /// </param>
        /// <param name="commands">
        /// The commands.
        /// </param>
        private void UpdateHotkey(object sender, int commandIndex, Collection<MenuCommand> commands)
        {
            if (this.initializing)
            {
                return;
            }

            ComboBox ctrl = sender as ComboBox;

            if (ctrl == null)
            {
                return;
            }

            if (commands.Count > commandIndex)
            {
                if (ctrl.SelectedItem == null)
                {
                    commands[commandIndex].HotKey = Keys.None;
                    return;
                }

                commands[commandIndex].HotKey = (Keys)Enum.Parse(typeof(Keys), ctrl.SelectedItem.ToString());
            }
        }

        /// <summary>
        /// The update hotkey modifier.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="commandIndex">
        /// The command index.
        /// </param>
        /// <param name="modifierIndex">
        /// The modifier index.
        /// </param>
        /// <param name="commands">
        /// The commands.
        /// </param>
        private void UpdateHotkeyModifier(object sender, int commandIndex, int modifierIndex, IEnumerable<MenuCommand> commands)
        {
            if (this.initializing)
            {
                return;
            }

            CheckBox ctrl = sender as CheckBox;

            if (ctrl == null)
            {
                return;
            }

            Dictionary<int, int> commandIndices = new Dictionary<int, int>();

            foreach (MenuCommand cmd in commands)
            {
                int menuId = 0;

                if (cmd is MenuCommandGoTo)
                {
                    menuId = ((MenuCommandGoTo)cmd).MenuId;
                }

                if (commandIndices.ContainsKey(menuId))
                {
                    commandIndices[menuId]++;
                }
                else
                {
                    commandIndices.Add(menuId, 0);
                }

                if (commandIndices[menuId] == commandIndex)
                {
                    switch (modifierIndex)
                    {
                        case 1:
                            cmd.HotKeyModifier1 = ctrl.Checked ? Keys.Control : Keys.None;
                            break;
                        case 2:
                            cmd.HotKeyModifier2 = ctrl.Checked ? Keys.Alt : Keys.None;
                            break;
                        case 3:
                            cmd.HotKeyModifier3 = ctrl.Checked ? Keys.Shift : Keys.None;
                            break;
                        default:
                            return;
                    }
                }
            }
        }

        /// <summary>
        /// The update profile check box validated.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void UpdateProfileCheckBoxValidated(object sender, EventArgs e)
        {
            this.settings.UpdateProfile = this.updateProfileCheckBox.Checked;
        }

        /// <summary>
        /// The update profile properties.
        /// </summary>
        private void UpdateProfileProperties()
        {
            this.ignoreEvents = true;
            FilterProperty property = this.profilePropertiesListBox.SelectedItem as FilterProperty;
            Profile profile = this.profilesComboBox.SelectedItem as Profile;
            this.profilePropertyPerSourceDataGridView.Rows.Clear();
            ProfileProperty prop;

            if (property == null || profile == null)
            {
                this.profilePropertyGroupBox.Visible = false;
                this.profilePropertyDetailsGroupBox.Visible = false;
            }
            else
            {
                this.profilePropertyGroupBox.Visible = true;
                this.profilePropertyDetailsGroupBox.Visible = true;

                prop = profile.ProfileProperties[property.Id];

                if (property is FilterPropertyEnum)
                {
                    this.profilePropertyDefaultComboBox.Visible = true;
                    this.profilePropertyDefaultNumericUpDown.Visible = false;
                    this.profilePropertyPerMediaVideoComboBox.Visible = true;
                    this.profilePropertyPerMediaVideoNumericUpDown.Visible = false;
                    this.profilePropertyPerMediaTvComboBox.Visible = true;
                    this.profilePropertyPerMediaTvNumericUpDown.Visible = false;
                    this.profilePropertyDefaultComboBox.Items.Clear();
                    this.profilePropertyPerMediaVideoComboBox.Items.Clear();
                    this.profilePropertyPerMediaTvComboBox.Items.Clear();
                    this.valueEnumColumn.Items.Clear();
                    this.valueEnumColumn.Visible = true;
                    this.valueColumn.Visible = false;

                    FilterPropertyEnum propertyEnum = (FilterPropertyEnum)property;

                    foreach (int id in propertyEnum.FilterPropertyValueIds)
                    {
                        if (!this.settings.FilterPropertyValues[id].Enabled)
                        {
                            continue;
                        }

                        int i = this.profilePropertyDefaultComboBox.Items.Add(this.settings.FilterPropertyValues[id]);
                        this.profilePropertyPerMediaVideoComboBox.Items.Add(this.settings.FilterPropertyValues[id]);
                        this.profilePropertyPerMediaTvComboBox.Items.Add(this.settings.FilterPropertyValues[id]);
                        this.valueEnumColumn.Items.Add(this.settings.FilterPropertyValues[id]);

                        if (prop.DefaultValue == this.settings.FilterPropertyValues[id].Value)
                        {
                            this.profilePropertyDefaultComboBox.SelectedIndex = i;
                        }
                    }
                }
                else
                {
                    this.profilePropertyDefaultComboBox.Visible = false;
                    this.profilePropertyDefaultNumericUpDown.Visible = true;
                    this.profilePropertyPerMediaVideoComboBox.Visible = false;
                    this.profilePropertyPerMediaVideoNumericUpDown.Visible = true;
                    this.profilePropertyPerMediaTvComboBox.Visible = false;
                    this.profilePropertyPerMediaTvNumericUpDown.Visible = true;
                    this.profilePropertyDefaultNumericUpDown.Value = prop.DefaultValue;
                    this.profilePropertyPerSourceDataGridView.Columns[1].Visible = false;
                    this.profilePropertyPerSourceDataGridView.Columns[2].Visible = true;
                }

                if (prop is ProfilePropertyPerMediaType)
                {
                    this.profilePropertyTypePerMediaTypeRadioButton.Checked = true;
                    this.profilePropertyDetailsGroupBox.Visible = true;
                    this.profilePropertyTabControl.SelectedIndex = 0;

                    ProfilePropertyPerMediaType prop2 = (ProfilePropertyPerMediaType)prop;

                    if (prop2.Value.ContainsKey(MediaPortal.Player.g_Player.MediaType.Video))
                    {
                        if (property is FilterPropertyEnum)
                        {
                            bool found = false;

                            foreach (FilterPropertyValue item in this.profilePropertyPerMediaVideoComboBox.Items)
                            {
                                if (item.Value == prop2.Value[MediaPortal.Player.g_Player.MediaType.Video])
                                {
                                    this.profilePropertyPerMediaVideoComboBox.SelectedItem = item;
                                    found = true;
                                    break;
                                }
                            }

                            if (!found)
                            {
                                this.profilePropertyPerMediaVideoComboBox.SelectedIndex = -1;
                            }
                        }
                        else
                        {
                            this.profilePropertyPerMediaVideoNumericUpDown.Value = prop2.Value[MediaPortal.Player.g_Player.MediaType.Video];
                        }
                    }
                    else
                    {
                        this.profilePropertyPerMediaVideoComboBox.SelectedIndex = -1;
                        this.profilePropertyPerMediaVideoNumericUpDown.Value = 0;
                    }

                    if (prop2.Value.ContainsKey(MediaPortal.Player.g_Player.MediaType.TV))
                    {
                        if (property is FilterPropertyEnum)
                        {
                            bool found = false;

                            foreach (FilterPropertyValue item in this.profilePropertyPerMediaTvComboBox.Items)
                            {
                                if (item.Value == prop2.Value[MediaPortal.Player.g_Player.MediaType.TV])
                                {
                                    this.profilePropertyPerMediaTvComboBox.SelectedItem = item;
                                    found = true;
                                    break;
                                }
                            }

                            if (!found)
                            {
                                this.profilePropertyPerMediaTvComboBox.SelectedIndex = -1;
                            }
                        }
                        else
                        {
                            this.profilePropertyPerMediaTvNumericUpDown.Value = prop2.Value[MediaPortal.Player.g_Player.MediaType.TV];
                        }
                    }
                    else
                    {
                        this.profilePropertyPerMediaTvComboBox.SelectedIndex = -1;
                        this.profilePropertyPerMediaTvNumericUpDown.Value = 0;
                    }
                }
                else if (prop is ProfilePropertyPerSource)
                {
                    this.profilePropertyTypePerSourceRadioButton.Checked = true;
                    this.profilePropertyDetailsGroupBox.Visible = true;
                    this.profilePropertyTabControl.SelectedIndex = 1;
                    this.valueEnumColumn.ValueMember = "Self";
                    this.valueEnumColumn.DisplayMember = "DisplayName";

                    ProfilePropertyPerSource prop2 = (ProfilePropertyPerSource)prop;

                    foreach (KeyValuePair<string, int> pair in prop2.Value)
                    {
                        FilterPropertyValue value = null;

                        foreach (FilterPropertyValue item in this.valueEnumColumn.Items)
                        {
                            if (item.Value == pair.Value || value == null)
                            {
                                value = item;
                            }
                        }

                        this.profilePropertyPerSourceDataGridView.Rows.Add(pair.Key, value, pair.Value);
                    }
                }
                else
                {
                    this.profilePropertyTypeGlobalRadioButton.Checked = true;
                    this.profilePropertyDetailsGroupBox.Visible = false;
                }
            }

            this.ignoreEvents = false;
        }

        /// <summary>
        /// The update subtitles check box validated.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void UpdateSubtitlesCheckBoxValidated(object sender, EventArgs e)
        {
            this.settings.UpdateSubtitles = this.updateSubtitlesCheckBox.Checked;
        }

        /// <summary>
        /// The stereoscopic menu check box validated.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void StereoscopicMenuCheckBoxValidated(object sender, EventArgs e)
        {
            this.settings.StereoscopicMenu = this.stereoscopicMenuCheckBox.Checked;
        }

        #endregion
    }
}